home *** CD-ROM | disk | FTP | other *** search
- #ifdef TEST
- #include <stdio.h>
- #include <string.h>
- #include <time.h>
- #define NULLCHAR ((char *)0)
- #define NULLFILE ((FILE *)0)
- #define callocw calloc
- #define SCREENwidth 80
- char *strlwr(char *s);
- void rip(register char *s);
- void kwait (void *);
- #define BROWSER 1
- #else
- #include "global.h"
- #include "socket.h"
- #include "netuser.h"
- #include "commands.h"
- #include "session.h"
- #include "files.h"
- #ifdef MSDOS
- #include <conio.h>
- #include "ctype.h"
- #endif
- #endif
- #include "browser.h"
-
-
- #if !defined(_lint) && !defined(TEST)
- static char rcsid[] OPTIONAL = "$Id: browser.c,v 1.12 1997/09/07 00:31:16 root Exp root $";
- #endif
-
- #ifdef BROWSER
- struct parseparams {
- int title_input;
- int titleindex;
- char title[128];
- int marquee_input;
- int marqueeindex;
- char marquee[1024];
- char buf[512];
- int inword;
- int index;
- int lastwhite;
- int eat_semicolon;
- int preformatted;
- int nowrap;
- int center;
- int center_one;
- int listlevel;
- int listcount[10];
- int listtype[10];
- };
-
-
- #define OP_UNKNOWN -1
- #define OP_A 1
- #define OP_BR 2
- #define OP_CAPTION 3
- #define OP_CENTER 4
- #define OP_CONSUME 5
- #define OP_DD 6
- #define OP_DL 7
- #define OP_DT 8
- #define OP_FORM 9
- #define OP_FRAME 10
- #define OP_HEADER 11
- #define OP_H1 12
- #define OP_HR 13
- #define OP_IGNORE 14
- #define OP_IMAGE 15
- #define OP_INPUT 16
- #define OP_ISINDEX 17
- #define OP_LI 18
- #define OP_MARQUEE 19
- #define OP_OL 20
- #define OP_P 21
- #define OP_PRE 22
- #define OP_TABLE 23
- #define OP_TD 24
- #define OP_TH 25
- #define OP_TITLE 26
- #define OP_TR 27
- #define OP_UL 28
-
-
- static struct opcodes {
- const char *opcode;
- int value;
- } supported_opcodes[] = {
- { "!--", OP_IGNORE }, /* not a real tag, used by HTML comments */
- { "a", OP_A },
- { "br", OP_BR },
- { "caption", OP_CAPTION },
- { "center", OP_CENTER },
- { "comment", OP_CONSUME },
- { "dd", OP_DD },
- { "dl", OP_DL },
- { "dt", OP_DT },
- { "dir", OP_UL },
- { "form", OP_FORM },
- { "frame", OP_FRAME },
- { "h1", OP_H1 },
- { "h2", OP_HEADER },
- { "h3", OP_HEADER },
- { "h4", OP_HEADER },
- { "h5", OP_HEADER },
- { "h6", OP_HEADER },
- { "hr", OP_HR },
- { "img", OP_IMAGE },
- { "input", OP_INPUT },
- { "isindex", OP_ISINDEX },
- { "li", OP_LI },
- { "marquee", OP_MARQUEE },
- { "menu", OP_UL },
- { "ol", OP_OL },
- { "p", OP_P },
- { "pre", OP_PRE },
- { "script", OP_CONSUME },
- { "table", OP_TABLE },
- { "td", OP_TD },
- { "th", OP_TH },
- { "title", OP_TITLE },
- { "tr", OP_TR },
- { "ul", OP_UL },
- { NULLCHAR, OP_UNKNOWN }
- };
-
-
- #define INPUT_UNKNOWN -1
- #define INPUT_CHECKBOX 1
- #define INPUT_HIDDEN 2
- #define INPUT_IMAGE 3
- #define INPUT_PASSWORD 4
- #define INPUT_RADIO 5
- #define INPUT_RESET 6
- #define INPUT_SUBMIT 7
- #define INPUT_TEXT 8
-
-
- static struct opcodes supported_inputs[] = {
- { "checkbox", INPUT_CHECKBOX },
- { "hidden", INPUT_HIDDEN },
- { "image", INPUT_IMAGE },
- { "password", INPUT_PASSWORD },
- { "radio", INPUT_RADIO },
- { "reset", INPUT_RESET },
- { "submit", INPUT_SUBMIT },
- { "text", INPUT_TEXT },
- { NULLCHAR, INPUT_UNKNOWN }
- };
-
-
- #define NBSP 300 /* special 'char' value for a non-breakable space */
- #define SECS_IN_6MONTHS 15768000 /* seconds in 1/2 year */
-
- static char HLINE[] = "--------------------------------------------------------------------------";
-
- static const char *HEADLINENewsHost = "www.lantz.com";
- static const char *HEADLINENewsUrl = "/tnos/headline_news.html";
-
-
- static void scroll_marquee (struct browser *br);
- static int gethead (const char *url, char *location, char *modified, char *content);
- static char *rebuild_url (struct browser *br, char *cp);
- static char *get_tag_data (struct browser *br, FILE *fp, char **cur_url, struct tag **cur_tag);
- static void parse_and_format_table (struct browser *br, struct parseparams *p, FILE *fp, int border);
- static void trim_trailing_white (char *str);
- static int disect_url (char *url, char *type, char *host, int *port, char *component);
- static char *build_url (struct browser *br, char *type, char *host, int port, char *component);
- static void parse_url (struct browser *br, FILE *fp, int headersexist);
- static int opcode_lookup (struct opcodes *op, char *opcode);
- static void add_char (struct parseparams *p, struct browser *br, int c);
- static void break_line (struct browser *br, struct parseparams *p);
- static void carryover_check (struct browser *br, struct parseparams *p);
- static char *alloc_string (struct browser *br, const char *str, int centerit);
- #ifndef TEST
- static int http_connect (char const *host, int port, struct sockaddr_in *fsocket);
- static void share_cookies (int s, char const *host, char const *component);
- static void add_cookie (char *host, char *path, time_t expires, char *name, char *value);
- static int get_url (struct browser *br, const char *url, const char *post, int postmode, char *enctype, int storeit);
- static void blank_status (struct browser *br);
- static void send_blank_lines (int count);
- static int http_url_to_file (struct browser *br, char *refered, char const *host, int port, char const *component, char *auth, FILE *fp, const char *post, int postmode, char *enctype, int quiet);
- static void clear_browser (struct browser *br);
- static void render_screen (struct browser *br);
- static void spawn_telnet (int port, void *host, void *p);
- static void spawn_ftp (int unused, void *host, void *file);
- static void send_mailto (char *addr);
- static void goto_stat (struct browser *br, int plusoffset);
- static void add_string (struct parseparams *p, struct browser *br, const char *str);
- static void end_link (struct parseparams *p, struct browser *br, int c);
- static void start_link (struct parseparams *p, struct browser *br, char *url, struct formlink *fl, int c);
- static char *encode_post (char *str);
-
- extern unsigned char SCREENlength, SCREENwidth;
- extern char shortversion[];
- extern char *strToBase64 (char *str);
- extern struct cmds Cmds[];
-
- static char *BrowserEmail = NULLCHAR;
-
-
- #define STATUS_LINES 3
-
- #ifdef MSDOS
- #define SCREENLENGTH (SCREENlength + 1)
- #else
- #define SCREENLENGTH (SCREENlength)
- #endif
-
- #endif
-
-
-
- static int
- opcode_lookup (struct opcodes *op, char *opcode)
- {
- for ( ; op->opcode; op++) {
- if (!strcasecmp (op->opcode, opcode))
- return op->value;
- }
- return OP_UNKNOWN;
- }
-
-
-
- #ifndef TEST
-
- /* fetch the specified URL
- returns -1 if cannot retrieve URL, 0 if no error, 1 if spawned other handler */
- static int
- get_url (struct browser *br, const char *url, const char *post, int postmode, char *enctype, int storeit)
- {
- FILE *fp;
- char type[12], host[100], component[512];
- int port, k;
- int retval = 0;
- char *tmp;
- char *refered = NULLCHAR;
-
- redirection:
-
- if (url == NULLCHAR)
- return -1;
-
- #if 1
- br->savingonly = 0;
- if (gethead (url, NULLCHAR, NULLCHAR, component) == 1) {
- /* exists (and is http), so check content type here */
- tmp = skipwhite (component);
- if (strncasecmp (tmp, "text/", 5)) {
- /* not text, so prompt for whether to get it */
- blank_status (br);
- Current->ttystate.edit = Current->ttystate.echo = 1;
- goto_stat (br, 0);
- cputs ("This URL cannot be displayed: ");
- cputs (url);
- cputs (Eol);
- cputs (" Save it to disk? ");
-
- kwait (NULL);
- (void) recvline (Curproc->input, (unsigned char *) host, 100);
- rip (host);
-
- Current->ttystate.edit = Current->ttystate.echo = 0;
- if (tolower(*host) != 'y')
- return -1;
- br->savingonly = 1;
- }
- }
- #endif
-
- fp = tmpfile ();
- if (fp == NULLFILE)
- return -1; /* shouldn't happen */
-
- tmp = strdup (url);
- if (disect_url (tmp, type, host, &port, component))
- return -1;
- if (!*host) {
- strncpy (host, component, 100);
- strcpy (component, "/");
- }
- free (tmp);
-
- if (storeit) {
- /* add this link to the linkback buffer */
- if (br->current_linkback == (LINKBACKS - 1)) {
- /* roll one off the top */
- free (br->linkback[0]);
- for (k = 1; k < LINKBACKS; k++)
- br->linkback[k - 1] = br->linkback[k];
- br->total_in_linkback--;
- br->current_linkback--;
- }
- if ((br->current_linkback || br->total_in_linkback) && br->current_linkback != (br->total_in_linkback - 1)) {
- /* overwritting a previous entry - clear all that follow */
- for (k = br->current_linkback + 1; k < br->total_in_linkback; k++) {
- free (br->linkback[k]);
- br->linkback[k] = NULLCHAR;
- }
- br->total_in_linkback = br->current_linkback + 1;
- }
- br->linkback[br->total_in_linkback++] = strdup (url);
- br->current_linkback = br->total_in_linkback - 1;
- }
-
-
- if (!strcasecmp (type, "telnet")) {
- (void) newproc ("tel_browser", 1024, spawn_telnet, port, host, NULL, 0);
- (void) kwait (NULL);
- return 1;
- } else if (!strcasecmp (type, "ftp")) {
- (void) newproc ("ftp_browser", 1024, spawn_ftp, 0, host, component, 0);
- (void) kwait (NULL);
- return 1;
- } else if (!strcasecmp (type, "mailto")) {
- send_mailto (component);
- return 1;
- } else if (!strcasecmp (type, "file")) {
- fp = fopen (component, "r");
- if (fp != NULLFILE) {
- clear_browser (br);
- br->current_url = build_url (br, type, host, port, component);
- parse_url (br, fp, 0);
- (void) fclose (fp);
- return 0;
- }
- return -1;
- } else if (strcasecmp (type, "http")) {
- /* don't do anything, for now */
- return 1;
- }
-
- refered = strdup (br->current_url);
- clear_browser (br);
- br->current_url = build_url (br, type, host, port, component);
-
- br->host = strdup (host);
- br->port = port;
-
- /* connect to the remote HTTP server, placing data into the tempfile */
- if ((retval = http_url_to_file (br, refered, host, port, component, br->auth, fp, post, postmode, enctype, 0)) == 0)
- parse_url (br, fp, 1);
-
- (void) fclose (fp);
- free (refered);
-
- /* check to see if there was a redirection to a new URL */
- if (br->redirect) {
- if (storeit) {
- /* back up the backlink, to make this invisible */
- br->current_linkback--;
- br->total_in_linkback--;
- }
- url = br->redirect;
- goto redirection;
- }
-
- /* check to see if there was an authorization error */
- if (br->auth) {
- /* Try again with the desired authorization info */
- if (storeit) {
- /* back up the backlink, to make this invisible */
- br->current_linkback--;
- br->total_in_linkback--;
- }
- url = br->current_url;
- goto redirection;
- }
-
- return retval;
- }
- #endif
-
-
-
- /* build a URL from type, host, port, and component and current host info*/
- static char *
- build_url (struct browser *br, char *type, char *host, int port, char *component)
- {
- char buf[512], portstr[16], namebuf[128];
- char *usehost;
-
- if (port != 80)
- sprintf (portstr, ":%d", port);
- else
- portstr[0] = 0;
-
- if (!strcasecmp (type, "mailto"))
- sprintf (buf, "%s:%s", type, component);
- else if (!strcasecmp (type, "file"))
- sprintf (buf, "%s:/%s", type, component);
- else {
- usehost = (*host) ? host : br->host;
- sprintf (namebuf, "%s:/%s%s", type, (*usehost == '/') ? "" : "/",
- usehost);
- if (namebuf[strlen(namebuf) - 1] == '/')
- namebuf[strlen(namebuf) - 1] = 0;
- sprintf (buf, "%s%s%s%s", namebuf, portstr,
- (component[0] == '/') ? "" : "/", component);
- }
- return strdup (buf);
- }
-
-
-
- /* disect the URL named into type, host, port, and component */
- /* component will NOT start with a '/' for relative URL's */
- static int
- disect_url (char *url, char *type, char *host, int *port, char *component)
- {
- char *cp;
-
- host[0] = ' ';
- if (!strncasecmp (url, "mailto:", 7)) {
- /* special case for mailto's */
- strcpy (component, &url[7]);
- strcpy (type, "mailto");
- return 0;
- }
-
- if (!strncasecmp (url, "file:", 5)) {
- cp = &url[5];
- if (*cp == '/' && cp[1] == '/')
- cp++;
- strcpy (component, cp);
- strcpy (type, "file");
- return 0;
- }
-
- if (strchr (url, ':') && strncasecmp (url, "ftp:", 4) &&
- strncasecmp (url, "telnet:", 7) && strncasecmp (url, "http:", 5))
- return -1;
-
- host[0] = 0;
- *port = 80;
- strcpy (type, "http");
- strcpy (component, "/");
-
- /* first we look for urls with a scheme name */
- if ((cp = strstr (url, ":/")) != NULLCHAR) {
- *cp++ = 0;
- strcpy (type, url);
- url = cp;
- }
-
- /* next we look to see if this is a network path */
- if (!strncmp (url, "//", 2)) {
- url += 2;
- cp = strpbrk (url, ":/?;");
- if (cp) {
- /* there is more to this address */
- if (*cp == ':') { /* contains a port number */
- *cp++ = 0;
- strcpy (host, url);
- url = cp;
- cp = strchr (url, '/');
- if (cp) {
- *cp++ = 0;
- strcpy (&component[1], cp);
- }
- *port = atoi (url);
- return 0;
- }
- /* otherwise, no port number */
- *cp++ = 0;
- strcpy (host, url);
- strcpy (&component[1], cp);
- return 0;
- }
- strcpy (host, url);
- return 0;
- }
-
- /* otherwise, it is either an absolute or relative path on this host */
- strcpy (component, url);
- return 0;
- }
-
-
-
-
- #ifndef TEST
-
- static void
- clear_browser (struct browser *br)
- {
- int k;
- struct formlink *fl, *last;
-
- /* first we cleanup any previous url info */
- for (k = 0; k < br->lines_in_url; k++) {
- free (br->display_lines[k]);
- br->display_lines[k] = NULLCHAR;
- }
-
- free (br->current_url);
- br->current_url = NULLCHAR;
-
- free (br->redirect);
- br->redirect = NULLCHAR;
-
- free (br->host);
- br->host = NULLCHAR;
-
- free (br->title);
- br->title = NULLCHAR;
-
- free (br->marquee);
- br->marquee = NULLCHAR;
- br->marquee_position = 0;
-
- br->has_an_index = br->lines_in_url = br->current_top_line = 0;
-
- for (k = 0; k < br->link_count; k++) {
- free (br->links[k].url);
- br->links[k].url = NULLCHAR;
- br->links[k].startline = br->links[k].endline = 0;
- br->links[k].startcolumn = br->links[k].endcolumn = 0;
- br->links[k].flink = NULLFLINK;
- br->links_per_line[k] = 0;
- }
-
- br->consume = br->status = br->link_count = br->current_link = 0;
-
- if (br->form != NULLFORM) {
- free (br->form->action);
- free (br->form->enctype);
-
- for (fl = br->form->flink; fl != NULLFLINK; fl = last) {
- last = fl->next;
- free (fl->data);
- free (fl->name);
- free (fl->value);
- free (fl->align);
- free (fl);
- }
- free (br->form);
- br->form = NULLFORM;
- }
- }
-
-
-
- static int
- http_connect (char const *host, int port, struct sockaddr_in *fsocket)
- {
- int s;
-
- fsocket->sin_family = AF_INET;
- fsocket->sin_port = (int16) port;
-
- if ((fsocket->sin_addr.s_addr = resolve (host)) == 0)
- return -1;
-
- if ((s = socket (AF_INET, SOCK_STREAM, 0)) == -1)
- return -1;
-
- (void) sockmode (s, SOCK_ASCII);
- if (connect (s, (char *) fsocket, SOCKSIZE) == -1)
- return -1;
-
- return s;
- }
-
-
-
- /* connects to remote HTTP server, and saves URL data
- returns -1 if cannot retrieve URL, 0 if no error */
- static int
- http_url_to_file (struct browser *br, char *refered, char const *host, int port, char const *component, char *auth, FILE *fp, const char *post, int postmode, char *enctype, int quiet)
- {
- struct sockaddr_in fsocket;
- int s, c;
- char *saved, *cp;
- int incomingcount = 0;
- char buf[20];
- int endofline = 0;
-
- /* telnet to 'host', port 'port', and send a request for 'component' */
- /* return -1 if can't connect or http error */
-
- s = http_connect (host, port, &fsocket);
- if (s == -1)
- return s;
-
- if (!quiet) {
- blank_status (br);
- goto_stat (br, 1);
- cputs ("Opening - http://");
- cputs (host);
- cputs (component);
- cputs ("...");
- }
-
- saved = strdup (component);
- if ((cp = strchr (saved, '#')) != NULLCHAR)
- *cp = 0;
-
- if (!quiet) {
- goto_stat (br, 2);
- cputs ("Sending request...");
- rflush ();
- }
-
- /* send the request to the server */
- usprintf (s, "%s %s%s%s HTTP/1.0\nHost: %s\nUser-Agent: %s\n",
- (post != NULLCHAR && postmode == 0) ? "POST" : "GET",
- saved, (post != NULLCHAR && postmode == 1) ? "?" : "",
- (post != NULLCHAR && postmode == 1) ? post : "",
- Hostname, shortversion);
- free (saved);
-
- #if 0
- usputs (s, "Accept: text/html, text/plain\n");
- #endif
- usputs (s, "Accept-Language: en\nPragma: no-cache\n");
- usprintf (s, "Cache-Control: no-cache\n");
- if (BrowserEmail != NULLCHAR)
- usprintf (s, "From: %s\n", BrowserEmail);
- else
- usprintf (s, "From: wwwuser@%s\n", Hostname);
- if (refered && *refered)
- usprintf (s, "Referer: %s\n", refered);
- if (auth)
- usprintf (s, "Authorization: Basic %s\n", auth);
- if (post != NULLCHAR && postmode == 0) {
- if (enctype != NULLCHAR) /* should always be non-null */
- usprintf (s, "Content-type: %s\n", enctype);
- usprintf (s, "Content-Length: %d\n", strlen (post) + 1);
- }
- #ifndef TEST
- share_cookies (s, host, component);
- #endif
-
- usputc (s, '\n');
- if (post != NULLCHAR && postmode == 0) {
- usputs (s, post);
- usputc (s, '\n');
- }
-
- if (!quiet) {
- goto_stat (br, 2);
- cputs ("Request sent... ");
- rflush ();
- }
-
- kwait (NULL);
-
- /* then while connection still open, store data into 'fp' */
- while ((c = recvchar (s)) != EOF) {
- if (br->savingonly && c == '\n') {
- if (endofline)
- (void) sockmode (s, SOCK_BINARY);
- endofline = 1;
- } else
- endofline = 0;
- fputc (c, fp);
- incomingcount++;
- if (!quiet) {
- if (!(incomingcount % 50)) {
- goto_stat (br, 2);
- cputs ("Read ");
- sprintf (buf, "%d", incomingcount);
- cputs (buf);
- cputs (" bytes... ");
- rflush ();
- }
- }
- }
-
- close_s (s);
-
- if (!quiet) {
- goto_stat (br, 2);
- cputs ("Read Complete... ");
- rflush ();
- }
-
- /* and reset to file for the next routine */
- rewind (fp);
- return 0;
- }
- #endif
-
-
-
- /* this routine allocates a string, optionally centering it */
- static char *
- alloc_string (struct browser *br, const char *str, int centerit)
- {
- char *buf;
- int len, k;
- struct url_links *lnk;
-
- buf = (char *) mallocw (((strlen(str) > SCREENwidth) ? strlen(str) : SCREENwidth) + 2);
- if (centerit) {
- len = (int) (SCREENwidth - strlen (str));
- if (len < 0)
- len = 0;
- len /= 2;
- sprintf (buf, "%*.*s%s", len, len, " ", str);
-
- /* We must also adjust any links on the current line */
- for (lnk = br->links, k = 0; k < br->link_count; k++,lnk++) {
- if (lnk->startline == br->lines_in_url)
- lnk->startcolumn += len;
- if (lnk->endline == br->lines_in_url)
- lnk->endcolumn += len;
- }
- } else
- strcpy (buf, str);
-
- return buf;
- }
-
-
-
- static void
- carryover_check (struct browser *br, struct parseparams *p)
- {
- char carryover[256];
- struct url_links *lnk;
- int length;
-
- if (br->lines_in_url >= MAX_URL_LINES || p->nowrap)
- return;
-
- if (p->index > (SCREENwidth - 1)) {
- if (p->lastwhite == 0)
- return;
- /* handle word wrap here */
- p->buf[p->lastwhite] = p->buf[p->index] = 0;
- br->display_lines[br->lines_in_url++] = alloc_string (br, p->buf, p->center);
- strcpy (carryover, &p->buf[p->lastwhite + 1]);
-
- if (p->listlevel)
- sprintf (p->buf, "%*.*s", (p->listlevel * 4) + 4,
- (p->listlevel * 4) + 4, " ");
- else
- p->buf[0] = 0;
-
- /* check if the last link needs adjusting */
- lnk = &br->links[br->link_count - 1];
- if (lnk->startline == (br->lines_in_url - 1) && lnk->startcolumn > p->lastwhite) {
- /* entire link on next line */
- lnk->startline++;
- lnk->endline++;
- length = lnk->endcolumn - lnk->startcolumn;
- if (p->listlevel)
- lnk->startcolumn = (p->listlevel * 4);
- else
- lnk->startcolumn = 0;
- lnk->endcolumn = lnk->startcolumn + length;
- if (lnk->flink != NULLFLINK) {
- lnk->flink->line = lnk->startline;
- lnk->flink->col = lnk->startcolumn + 1;
- }
- br->links_per_line[br->lines_in_url]++;
- br->links_per_line[br->lines_in_url - 1]--;
-
- } else if (lnk->endline == (br->lines_in_url - 1) && lnk->endcolumn > p->lastwhite) {
- /* end of link needs adjusting */
- lnk->endline++;
- lnk->endcolumn = (int) (strlen (p->buf) - 1);
- br->links_per_line[br->lines_in_url]++;
- }
-
- strcat (p->buf, carryover);
- p->index = (int) strlen (p->buf);
- p->lastwhite = 0;
- }
-
- }
-
-
-
- static void
- break_line (struct browser *br, struct parseparams *p)
- {
- carryover_check (br, p);
- p->buf[p->index] = 0;
- if (p->index && (br->lines_in_url < MAX_URL_LINES))
- br->display_lines[br->lines_in_url++] = alloc_string (br, p->buf, p->center + p->center_one);
- p->index = p->lastwhite = p->inword = 0;
- p->center_one = 0;
- }
-
-
-
- static void
- start_link (struct parseparams *p, struct browser *br, char *url, struct formlink *fl, int c)
- {
- if (br->link_count < MAX_URL_LINKS) {
- br->links[br->link_count].startline = br->lines_in_url;
- br->links[br->link_count].url = url;
- br->links[br->link_count].flink = fl;
- br->links_per_line[br->lines_in_url]++;
- if (c && p->index && p->buf[p->index - 1] != ' ')
- add_char (p, br, ' ');
- br->links[br->link_count].startcolumn = p->index;
- if (c)
- add_char (p, br, c);
- }
- p->inword = 0;
- }
-
-
-
- static void
- end_link (struct parseparams *p, struct browser *br, int c)
- {
- char buf[2];
- int k;
-
- if (br->link_count < MAX_URL_LINKS) {
- if (c && p->index && p->buf[p->index - 1] == ' ')
- p->index--;
- if (!p->index) {
- /* adjust this back to the end of the last line */
- strcpy (p->buf, br->display_lines[br->lines_in_url - 1]);
- buf[0] = (char) c;
- buf[1] = 0;
- strcat (p->buf, buf);
- free (br->display_lines[br->lines_in_url - 1]);
- br->display_lines[br->lines_in_url - 1] = strdup (p->buf);
- br->links[br->link_count].endline = br->lines_in_url - 1;
- br->links[br->link_count].endcolumn = (int) (strlen (p->buf) - 1);
- } else {
- if (c)
- add_char (p, br, c);
- br->links[br->link_count].endline = br->lines_in_url;
- br->links[br->link_count].endcolumn = p->index - 1;
- }
- for (k = br->links[br->link_count].startline + 1; k <= br->links[br->link_count].endline; k++)
- br->links_per_line[k]++;
- br->link_count++;
- }
- }
-
-
-
- static void
- add_string (struct parseparams *p, struct browser *br, const char *str)
- {
- while (*str)
- add_char (p, br, *str++);
- }
-
-
-
- static void
- add_char (struct parseparams *p, struct browser *br, int c)
- {
- if (br->consume)
- return;
-
- if (c == ' ' || c == '\t' || c == '\n') {
- if (p->title_input) {
- p->title[p->titleindex++] = ' ';
- return;
- }
- if (p->marquee_input) {
- p->marquee[p->marqueeindex++] = ' ';
- return;
- }
- if (!p->preformatted && !p->inword)
- return; /* eat multiple white */
- p->inword = 0;
- if (p->index > (SCREENwidth - 1))
- carryover_check (br, p);
-
- p->lastwhite = p->index;
- p->buf[p->index++] = (p->preformatted) ? (char) c : ' ';
- return;
- }
-
- if (c == NBSP)
- c = ' ';
-
- if (c == ';' && p->eat_semicolon) {
- p->eat_semicolon = 0;
- return;
- }
- p->eat_semicolon = 0;
- if (p->title_input) {
- p->title[p->titleindex++] = (char) c;
- return;
- }
- if (p->marquee_input) {
- p->marquee[p->marqueeindex++] = (char) c;
- return;
- }
- p->inword = 1;
- if (!p->index && p->listlevel) {
- sprintf (p->buf, "%*.*s", (p->listlevel * 4) + 4,
- (p->listlevel * 4) + 4, " ");
- p->index = (int) strlen (p->buf);
- p->lastwhite = p->index - 1;
- }
- p->buf[p->index++] = (char) c;
- }
-
-
-
- /* cp is malloced, and gets freed. this returns a new malloced string */
- static char *
- rebuild_url (struct browser *br, char *cp)
- {
- char *saved, *temp, *cp3;
- char type[12], host[100], component[512];
- int port;
- int badurl = 0;
-
- badurl = disect_url (cp, type, host, &port, component);
- free (cp);
-
- if (!badurl) {
-
- if (*component != '/' && !strcasecmp (type, "http")) { /* relative URL */
- saved = strdup (component);
- temp = strdup (br->current_url);
- (void) disect_url (temp, type, host, &port, component);
- if ((cp3 = strrchr (component, '/')) != NULLCHAR)
- cp3++;
- else
- cp3 = component;
- strcpy (cp3, saved);
- free (saved);
- free (temp);
- }
-
- cp = build_url (br, type, host, port, component);
- } else
- cp = NULLCHAR;
- return cp;
- }
-
-
- /* parse the tempfile given (containing the raw URL data)
- and place into the browser structure
- currently bitbuckets all http header lines */
- static void
- parse_url (struct browser *br, FILE *fp, int headersexist)
- {
- struct parseparams *p;
- struct tag *tag;
- struct formlink *fl;
- char url[128];
- int headers_done = 0;
- int c, k;
- char host[100], component[512];
- char *cp;
- int linkfound = 0;
- char *realm = NULLCHAR;
- struct realms *rl;
- int badauth = 0;
- int saveinstead = 0;
- #ifndef TEST
- FILE *savefp = NULLFILE;
- #endif
-
- p = (struct parseparams *) callocw (1, sizeof (struct parseparams));
-
- if (headersexist) {
- /* first line contains request status */
- (void) fgets (p->buf, 128, fp);
- if ((cp = strchr (p->buf, ' ')) != NULLCHAR)
- br->status = atoi (++cp);
- else
- br->status = 0;
- } else
- headers_done = 1;
-
- /* skip all http header lines */
- while (!headers_done) {
- (void) fgets (p->buf, 128, fp);
- rip (p->buf);
- if (!*p->buf)
- break;
- if (!strncasecmp (p->buf, "Content-type: ", 14)) {
- if (strncmp (&p->buf[14], "text", 4))
- /* if not a text URL, so we save it */
- saveinstead = 1;
- }
-
- #ifndef TEST
- if (!strncasecmp (p->buf, "Set-Cookie: ", 12)) {
- /* parse line, and call add_cookie here */
- char *hostnm = NULLCHAR, *path = NULLCHAR, *name = NULLCHAR, *value = NULLCHAR;
- char *tmp;
- time_t expires = 0;
-
- cp = &p->buf[12];
- while (cp && *cp) {
- cp = skipwhite (cp);
- if (!strncasecmp (cp, "domain=", 7)) {
- cp += 7;
- tmp = strchr (cp, ';');
- if (tmp)
- *tmp++ = 0;
- hostnm = strdup (cp);
- cp = tmp;
- } else if (!strncasecmp (cp, "path=", 5)) {
- cp += 5;
- tmp = strchr (cp, ';');
- if (tmp)
- *tmp++ = 0;
- path = strdup (cp);
- cp = tmp;
- } else if (!strncasecmp (cp, "expires=", 8)) {
- /* ignore this, treat all expires as + 6 months */
- tmp = strchr (cp, ';');
- if (tmp)
- cp = tmp;
- else
- cp = &cp[strlen(cp)];
- } else if (!strncasecmp (cp, "secure", 6)) {
- /* not supported, just skip it */
- cp = skipnonwhite (cp);
- } else if ((tmp = strchr (cp, '=')) != NULLCHAR) {
- /* this is the name=value string */
- *tmp++ = 0;
- name = strdup (cp);
- cp = strchr (tmp, ';');
- if (cp)
- *cp++ = 0;
- value = strdup (tmp);
- }
- if (cp) {
- cp = skipwhite (cp);
- if (*cp == ';')
- cp++;
- }
- }
- if (path == NULLCHAR) {
- tmp = strchr (br->current_url, '/');
- if (tmp) {
- tmp += 2;
- tmp = strchr (tmp, '/');
- path = strdup (tmp);
- } else
- path = strdup ("/");
- }
- if (hostnm == NULLCHAR)
- hostnm = strdup (br->host);
- expires = time ((time_t *)0) + SECS_IN_6MONTHS;
-
- add_cookie (hostnm, path, expires, name, value);
- free (hostnm);
- free (path);
- free (name);
- free (value);
- continue;
- }
-
- /* if we are being redirected, then get the new URL */
- if (br->status == 302 && !strncasecmp (p->buf, "Location: ", 10)) {
- br->redirect = strdup (&p->buf[10]);
- return;
- }
-
- /* if we need authorization, then get it */
- if (br->status == 401 && !strncasecmp (p->buf, "WWW-Authenticate: ", 18)) {
- if ((cp = strstr (p->buf, "basic")) == NULLCHAR)
- continue; /* only basic auth supported */
- if ((cp = strstr (p->buf, "realm=\"")) != NULLCHAR) {
- realm = strdup (&cp[7]);
- if ((cp = strchr (realm, '"')) != NULLCHAR)
- *cp = 0;
- }
-
- /* first look to see if we already know how to answer this one */
- for (rl = br->myrealms; rl; rl = rl->next) {
- if (realm && !strcasecmp (realm, rl->realm)) {
- if (br->auth && !strcmp (br->auth, rl->auth)) {
- /* we already USED this authentication, and it failed! */
- badauth = 1;
- free (rl->auth);
- rl->auth = NULLCHAR;
- free (br->auth);
- break;
- }
- free (realm);
- free (br->auth);
- br->auth = NULLCHAR;
- br->auth = strdup (rl->auth);
- return;
- }
- }
-
- /* nope, this is a new one */
- blank_status (br);
- goto_stat (br, 0);
- sprintf (component, "Enter authentication information for %s at %s",
- (realm) ? realm : "selected URL", br->host);
- cputs (component);
- Current->ttystate.edit = Current->ttystate.echo = 1;
- goto_stat (br, 1);
- cputs (" User Name: ");
- kwait (NULL);
- (void) recvline (Curproc->input, (unsigned char *) url, 100);
- rip (url);
-
- Current->ttystate.echo = 0;
- if (*url) {
- goto_stat (br, 2);
- cputs (" Password: ");
- kwait (NULL);
- (void) recvline (Curproc->input, (unsigned char *) host, 100);
- rip (host);
-
- sprintf (component, "%s:%s", url, host);
- br->auth = strToBase64 (component);
-
- /* and add to my current realms */
- if (!badauth) {
- rl = (struct realms *) callocw (1, sizeof (struct realms));
- if (rl != NULLREALMS) {
- rl->next = br->myrealms;
- br->myrealms = rl;
- rl->host = strdup (br->host);
- rl->realm = strdup (realm);
- }
- }
- if (rl != NULLREALMS)
- rl->auth = strdup (br->auth);
- }
-
- Current->ttystate.edit = 0;
- free (realm);
- if (*url)
- return;
- }
-
-
- /* else, bitbucket any other headers, for now */
- #endif
- }
-
- free (br->auth);
- br->auth = NULLCHAR;
-
- #ifndef TEST
- if (saveinstead) {
- cp = strrchr (br->current_url, '/');
- if (!cp) /* it always WILL be nonzero - this is for lint */
- return;
- sprintf (component, "%s%s", IncomingURLs, cp);
- (void) mkdir (IncomingURLs, 0777); /* create, just in case */
- savefp = fopen (component, WRITE_BINARY);
- if (savefp == NULLFILE)
- return;
- }
- #endif
-
- kwait (NULL);
- /* the rest of the file is the data of the URL */
- while ((c = fgetc (fp)) != EOF) {
- #ifndef TEST
- if (savefp != NULLFILE) {
- fputc (c, savefp);
- continue;
- }
- #endif
- if (p->preformatted && c != '<') {
- if (c == '\n') {
- c = p->index;
- break_line (br, p);
- if (c == 0)
- br->display_lines[br->lines_in_url++] = strdup ("");
- } else
- add_char (p, br, c);
- continue;
- }
-
- switch (c) {
- case '\r':
- break; /* eat it */
-
- case '&':
- switch (tolower (fgetc (fp))) {
- case 'l':
- if (tolower (fgetc (fp)) == 't') {
- add_char (p, br, '<');
- p->eat_semicolon = 1;
- }
- break;
- case 'g':
- if (tolower (fgetc (fp)) == 't') {
- add_char (p, br, '>');
- p->eat_semicolon = 1;
- }
- break;
- case 'n':
- if ((tolower (fgetc (fp)) == 'b') &&
- (tolower (fgetc (fp)) == 's') &&
- (tolower (fgetc (fp)) == 'p')) {
- add_char (p, br, NBSP);
- p->eat_semicolon = 1;
- }
- break;
- default:
- break;
- }
- break;
- case '<':
- tag = parse_tag (fp);
- switch (opcode_lookup (supported_opcodes, tag->name)) {
- case OP_CONSUME: /* used for SCRIPT tag */
- br->consume = (!tag->endtag) ? 1 : 0;
- break;
- case OP_IGNORE: /* used when a HTML comment is skipped */
- break;
- case OP_FORM:
- if (!tag->endtag) {
- cp = find_option (tag, "action", 0);
- if (cp == NULLCHAR)
- break;
- br->form = (struct form *) callocw (1, sizeof(struct form));
-
- cp = rebuild_url (br, cp);
- if (cp == NULLCHAR)
- break;
-
- br->form->action = strdup (cp);
- cp = find_option (tag, "enctype", 0);
- br->form->enctype = (cp == NULLCHAR) ? strdup ("application/x-www-form-urlencoded") : cp;
-
- cp = find_option (tag, "method", 0);
- if (cp != NULLCHAR && !strcasecmp (cp, "GET"))
- br->form->method = 1;
- free (cp);
- } else {
- struct formlink *fl2;
- int found;
- /* we need to insure that one radio button in each group is selected */
- for (fl = br->form->flink; fl != NULLFLINK; fl = fl->next) {
- if (fl->type == INPUT_RADIO && !fl->bool) {
- found = 0;
- for (fl2 = br->form->flink; fl2 != NULLFLINK; fl2 = fl2->next) {
- if (fl2 != fl && fl2->type == INPUT_RADIO && !strcmp (fl->name, fl2->name)) {
- if (fl2->bool) {
- found = 1;
- break;
- }
- }
- }
- if (!found) {
- fl->bool = 1;
- br->display_lines[fl->line][fl->col] = '*';
- }
-
- }
- }
- }
- break;
-
- case OP_PRE:
- p->preformatted = (tag->endtag) ? 0 : 1;
- break;
- case OP_OL:
- if (!tag->endtag)
- p->listtype[p->listlevel++] = 1;
- else if (p->listlevel)
- p->listlevel--;
- goto do_a_p;
- case OP_UL:
- if (!tag->endtag)
- p->listtype[p->listlevel++] = 0;
- else if (p->listlevel)
- p->listlevel--;
- goto do_a_p;
- case OP_DL:
- p->listlevel = 0;
- goto do_a_p;
- case OP_DT:
- if (!tag->endtag)
- break_line (br, p);
- p->listlevel = 0;
- break;
- case OP_DD:
- if (!tag->endtag) {
- p->listlevel = 1;
- break_line (br, p);
- }
- break;
- case OP_LI:
- if (!tag->endtag) {
- break_line (br, p);
- p->listcount[p->listlevel - 1]++;
- if (p->listtype[p->listlevel - 1])
- sprintf (p->buf, "%*.*s%2d. ", (p->listlevel * 4),
- (p->listlevel * 4), " ", p->listcount[p->listlevel - 1]);
- else
- sprintf (p->buf, "%*.*s* ", (p->listlevel * 4),
- (p->listlevel * 4), " ");
- p->index = (int) strlen (p->buf);
- p->lastwhite = p->index - 1;
- }
- break;
-
- case OP_IMAGE:
- /* look within here to see if an 'alt="xxx"' part is found */
- cp = find_option (tag, "alt", 0);
- if (cp == NULLCHAR)
- break;
- add_string (p, br, cp);
- free (cp);
- break;
-
- case OP_ISINDEX:
- br->has_an_index = 1;
- break;
- case OP_H1:
- if (!tag->endtag) {
- break_line (br, p);
- break;
- }
- /* first adjust the buffer to center the line */
- p->center_one = 1;
- /* and fall through */
- case OP_HEADER:
- case OP_P:
- do_a_p: break_line (br, p);
- if (br->lines_in_url && *br->display_lines[br->lines_in_url - 1])
- br->display_lines[br->lines_in_url++] = strdup ("");
- break;
- case OP_TITLE:
- if (!tag->endtag) {
- p->title_input = 1;
- p->titleindex = 0;
- } else {
- p->title_input = 0;
- p->title[p->titleindex] = 0;
- free (br->title);
- br->title = strdup (p->title);
- }
- break;
- case OP_MARQUEE:
- if (!tag->endtag) {
- p->marquee_input = 1;
- p->marqueeindex = 0;
- } else {
- p->marquee_input = 0;
- for (c = 0; c < SCREENwidth; c++)
- p->marquee[p->marqueeindex++] = ' ';
- p->marquee[p->marqueeindex] = 0;
- free (br->marquee);
- br->marquee = strdup (p->marquee);
- }
- break;
- case OP_TABLE:
- if (!tag->endtag) {
- cp = find_option (tag, "border", 0);
- if (cp == NULLCHAR)
- c = 1;
- else
- c = atoi (cp);
- free (cp);
- parse_and_format_table (br, p, fp, c);
- }
- break;
- case OP_CENTER:
- if (!tag->endtag) {
- p->center = p->center_one = 0;
- break_line (br, p);
- p->center = 1;
- } else {
- p->center = 0;
- p->center_one = 1;
- break_line (br, p);
- }
- break;
- case OP_BR:
- break_line (br, p);
- break;
- case OP_HR:
- break_line (br, p);
- br->display_lines[br->lines_in_url++] = strdup (HLINE);
- break;
- case OP_FRAME:
- cp = find_option (tag, "src", 0);
- if (cp == NULLCHAR)
- break;
- cp = rebuild_url (br, cp);
- if (cp == NULLCHAR)
- break;
- break_line (br, p);
- add_char (p, br, NBSP);
- add_char (p, br, NBSP);
- add_char (p, br, NBSP);
- start_link (p, br, cp, NULLFLINK, '[');
- add_string (p, br, "Frame: ");
- cp = find_option (tag, "name", 0);
- if (cp == NULLCHAR)
- cp = find_option (tag, "src", 0);
- add_string (p, br, cp);
- free (cp);
- end_link (p, br, ']');
- break_line (br, p);
- break;
- case OP_A:
- if (!tag->endtag) {
- cp = find_option (tag, "href", 0);
- if (cp == NULLCHAR)
- break;
-
- cp = rebuild_url (br, cp);
- if (cp == NULLCHAR)
- break;
- start_link (p, br, cp, NULLFLINK, '[');
- linkfound = 1;
- } else if (linkfound) {
- if ((br->links[br->link_count].startcolumn + 1) == p->index)
- /* empty, so we'll assume there is a graphic here */
- add_string (p, br, "Graphic");
-
- end_link (p, br, ']');
- linkfound = 0;
-
- }
- break;
- case OP_INPUT:
- if (br->form == NULLFORM)
- break;
- cp = find_option (tag, "type", 0);
- if (cp == NULLCHAR) /* spec says it's required, but the major browsers let it slide and default */
- k = INPUT_TEXT;
- else {
- k = opcode_lookup (supported_inputs, cp);
- free (cp);
- if (k == INPUT_UNKNOWN)
- break;
- }
- fl = (struct formlink *) callocw (1, sizeof(struct formlink));
- fl->type = k;
- if (br->form->lastlink == NULLFLINK)
- br->form->lastlink = br->form->flink = fl;
- else {
- br->form->lastlink->next = fl;
- br->form->lastlink = fl;
- }
- fl->name = find_option (tag, "name", 0);
- fl->value = find_option (tag, "value", 0);
- fl->align = find_option (tag, "align", 0);
-
- cp = find_option (tag, "size", 0);
- if (cp != NULLCHAR) {
- fl->size = atoi (cp);
- free (cp);
- }
- cp = find_option (tag, "maxlength", 0);
- if (cp != NULLCHAR) {
- fl->maxlength = atoi (cp);
- free (cp);
- }
-
- cp = find_option (tag, "selected", &k);
- if (k)
- fl->bool = 1;
- free (cp);
-
- if (fl->type == INPUT_HIDDEN)
- break;
- start_link (p, br, NULLCHAR, fl, (fl->type != INPUT_RADIO) ? '[' : '(');
- fl->line = br->lines_in_url;
- fl->col = p->index;
- switch (fl->type) {
- case INPUT_CHECKBOX:
- add_char (p, br, (fl->bool) ? 'X' : '_');
- break;
- case INPUT_RADIO:
- add_char (p, br, (fl->bool) ? '*' : '_');
- break;
- case INPUT_IMAGE:
- add_string (p, br, "Clickable Image");
- break;
- case INPUT_SUBMIT:
- add_string (p, br, (fl->value) ? fl->value : "Submit");
- break;
- case INPUT_RESET:
- add_string (p, br, (fl->value) ? fl->value : "Reset");
- break;
- case INPUT_PASSWORD:
- case INPUT_TEXT:
- for (k = 0; k < fl->size; k++)
- add_char (p, br, '_');
- break;
- default:
- break;
- }
- end_link (p, br, (fl->type != INPUT_RADIO) ? ']' : ')');
- add_char (p, br, ' ');
-
- break;
- default:
- break;
- }
- delete_tag (tag);
- break;
- default:
- add_char (p, br, c);
- break;
- }
- }
- break_line (br, p);
-
- /* now check for longest line length, and set it */
- br->longestline = br->columnoffset = 0;
- for (k = 0; k < br->lines_in_url; k++) {
- if ((int) strlen (br->display_lines[k]) > br->longestline)
- br->longestline = (int) strlen (br->display_lines[k]);
- }
-
- #ifndef TEST
- if (savefp != NULLFILE)
- (void) fclose (savefp);
- #endif
-
- /* if both an ISINDEX and an MARQUEE found, ISINDEX wins the status line */
- if (br->has_an_index && br->marquee) {
- free (br->marquee);
- br->marquee = NULLCHAR;
- }
- }
-
-
-
- static char *
- get_tag_data (struct browser *br, FILE *fp, char **cur_url, struct tag **cur_tag)
- {
- int theindex, c;
- char buf[1024], *cp;
- struct tag *tag;
- int done = 0;
- int eat_semicolon = 0;
-
- theindex = 0;
- buf[0] = 0;
-
- do {
- while ((c = fgetc (fp)) != '<') {
- #if 0
- if (c != '\n')
- buf[theindex++] = (char) c;
- #else
- switch (c) {
- case '&':
- switch (tolower (fgetc (fp))) {
- case 'l':
- if (tolower (fgetc (fp)) == 't') {
- buf[theindex++] = '<';
- eat_semicolon = 1;
- }
- break;
- case 'g':
- if (tolower (fgetc (fp)) == 't') {
- buf[theindex++] = '>';
- eat_semicolon = 1;
- }
- break;
- case 'n':
- if ((tolower (fgetc (fp)) == 'b') &&
- (tolower (fgetc (fp)) == 's') &&
- (tolower (fgetc (fp)) == 'p')) {
- buf[theindex++] = ' ';
- eat_semicolon = 1;
- }
- break;
- default:
- break;
- }
- break;
- case '\n':
- break; /* nothing, eat it */
- case ';':
- if (eat_semicolon) {
- eat_semicolon = 0;
- break;
- }
- /* else, fall-through */
- default:
- buf[theindex++] = (char) c;
- eat_semicolon = 0;
- }
- #endif
- }
- tag = parse_tag (fp);
- switch (opcode_lookup (supported_opcodes, tag->name)) {
- case OP_A: /* do 'A' tags here */
- if (!tag->endtag) {
- cp = find_option (tag, "href", 0);
- if (cp != NULLCHAR) {
- cp = rebuild_url (br, cp);
- if (cp == NULLCHAR)
- break;
- /* this only occurs if this data element had multiple links -
- all but the last one are lost */
- if (*cur_url != NULLCHAR)
- free (*cur_url);
- *cur_url = cp;
- }
- }
- delete_tag (tag);
- break;
- case OP_CAPTION:
- case OP_TR:
- case OP_TH:
- case OP_TD:
- case OP_TABLE:
- delete_tag (*cur_tag);
- *cur_tag = tag;
- done = 1;
- break;
- default: /* ignore it */
- delete_tag (tag);
- break;
- }
- } while (!done);
- buf[theindex] = 0;
- return (strdup (buf));
- }
-
-
-
- static void
- parse_and_format_table (struct browser *br, struct parseparams *p, FILE *fp, int border)
- {
- int c, done = 0, theindex, in_a_row = 0, offset;
- int column = 0, usecols, userows, size, thissize;
- int rowsize, tmp;
- struct tag *tag;
- char *cp;
- struct form_table *tbl;
- struct table_row *row, *newrow;
- struct table_column *col;
- int nowrap;
- char *cur_url = NULLCHAR;
- int reloop;
- int tablelevel = 1;
- int foundimbedded = 0;
-
- tbl = (struct form_table *) callocw (1, sizeof (struct form_table));
- row = tbl->rows;
-
- /* first we must parse the entire table tag (and sub-tags) */
- while (!done && (c = fgetc (fp)) != EOF) {
- if (c != '<')
- continue;
- tag = parse_tag (fp);
- loop: reloop = 0;
- switch (opcode_lookup (supported_opcodes, tag->name)) {
- case OP_CAPTION:
- if (!tag->endtag) {
- if (tbl->caption)
- free (tbl->caption);
- tbl->caption = get_tag_data (br, fp, &cur_url, &tag);
- reloop = 1;
- }
- break;
- case OP_TR: /* define a table row */
- if (tag->endtag || in_a_row) {
- /* ending a row */
- in_a_row = 0;
- if (tbl->rows[tbl->numrows].cols_in_row > tbl->numcols)
- tbl->numcols = tbl->rows[tbl->numrows].cols_in_row;
- tbl->numrows++;
- }
- if (!tag->endtag) {
- row = &tbl->rows[tbl->numrows];
- in_a_row = 1;
- column = row->cols_in_row;
- cp = find_option (tag, "align", 0);
- if (cp) {
- if (!strcasecmp ("center", cp))
- row->align = TABLE_ALIGN_CENTER;
- else if (!strcasecmp ("right", cp))
- row->align = TABLE_ALIGN_RIGHT;
- free (cp);
- }
- }
-
- if (column > tbl->numcols)
- tbl->numcols = column;
- break;
- case OP_TH: /* define a table heading */
- case OP_TD: /* define a table data element */
- if (tag->endtag)
- break;
- usecols = 1;
- col = &row->cols[row->cols_in_row];
- cp = find_option (tag, "colspan", 0);
- if (cp != NULLCHAR)
- usecols = atoi (cp);
- if (!usecols)
- usecols = 1;
- col->colspan = usecols;
- free (cp);
-
- userows = 1;
- cp = find_option (tag, "rowspan", 0);
- if (cp != NULLCHAR)
- userows = atoi (cp);
- if (!userows)
- userows = 1;
- free (cp);
-
- col->align = row->align;
- cp = find_option (tag, "align", 0);
- if (cp) {
- if (!strcasecmp ("center", cp))
- col->align = TABLE_ALIGN_CENTER;
- else if (!strcasecmp ("right", cp))
- col->align = TABLE_ALIGN_RIGHT;
- free (cp);
- }
-
- col->rowspan = userows;
- if (userows != 1) {
- newrow = &tbl->rows[tbl->numrows + 1];
- newrow->cols[newrow->cols_in_row].colspan = usecols;
- newrow->cols[newrow->cols_in_row].rowspan = 1;
- newrow->cols_in_row++;
- if (usecols != 1) {
- newrow->cols[newrow->cols_in_row].colspan = 1;
- newrow->cols[newrow->cols_in_row].rowspan = 1;
- newrow->cols_in_row++;
- }
- }
-
- cur_url = NULLCHAR;
- col->value = get_tag_data (br, fp, &cur_url, &tag);
- reloop = 1;
-
- /* now, if a A tag was found in this column, save it */
- if (cur_url != NULLCHAR)
- col->url = cur_url;
-
- rowsize = (int) strlen(col->value) / usecols;
- if (tbl->colsize[column] < rowsize)
- tbl->colsize[column] = rowsize;
-
- row->cols_in_row++;
- column++;
- if (usecols != 1) {
- while (--usecols) {
- col++;
- col->colspan = 1;
- col->rowspan = userows;
- row->cols_in_row++;
- tbl->colsize[column] = rowsize;
- column++;
- }
- }
- break;
- case OP_TABLE:
- /* this SHOULD be an endtag - assumed */
- if (!tag->endtag) {
- tablelevel++;
- foundimbedded++;
- } else
- tablelevel--;
- if (tablelevel == 0)
- done = 1;
- break;
- default:
- break;
- }
- if (reloop)
- goto loop;
- delete_tag (tag);
- }
- if (in_a_row)
- tbl->numrows++;
-
-
- if (foundimbedded) {
- break_line (br, p);
- add_string (p, br, "[ The following is a table with one or more imbedded tables - TNOS doesn't render these properly (at least not yet) ]");
- if (br->lines_in_url && *br->display_lines[br->lines_in_url - 1])
- br->display_lines[br->lines_in_url++] = strdup ("");
- break_line (br, p);
- }
-
- /* now we set column sizes where there were no headers for the columns */
- for (c = 0; c < tbl->numcols; c++) {
- if (!tbl->colsize[c]) { /* wasn't set by a header */
- column = 0;
- size = 1;
- for (theindex = 0, row = tbl->rows; theindex < tbl->numrows; theindex++,row++) {
- for (usecols = 0,col = row->cols; usecols < row->cols_in_row; usecols++,col++) {
- if (column < c) {
- column++;
- thissize = (int) strlen (col->value) / col->rowspan;
- if (col->value != NULLCHAR && size < thissize)
- size = thissize;
- }
- }
- }
- tbl->colsize[c] = size;
- }
- }
-
- #ifdef TEST
- printf ("Table:\n\tCaption: %s - Numcols: %d - Numrows: %d\n",
- (tbl->caption) ? tbl->caption : "none", tbl->numcols, tbl->numrows);
- for (c = 0; c < tbl->numcols; c++)
- printf ("\tColumn %d: size: %d", c, tbl->colsize[c]);
- for (c = 0; c < tbl->numrows; c++) {
- int cc;
- printf ("\tRow %d - cols_in_row: %d - align: %d\n",
- c, tbl->rows[c].cols_in_row, tbl->rows[c].align);
- for (cc = 0; cc < tbl->rows[c].cols_in_row; cc++)
- printf ("\tCol %d - colspan: %d, rowspan: %d, align: %d, value: '%s'\n",
- cc, tbl->rows[c].cols[cc].colspan,
- tbl->rows[c].cols[cc].rowspan, tbl->rows[c].cols[cc].align,
- tbl->rows[c].cols[cc].value);
- }
- #endif
- /* now we render the table */
- size = 1 + (tbl->numcols * 3);
- for (c = 0; c < tbl->numcols; c++)
- size += tbl->colsize[c];
-
- break_line (br, p);
- nowrap = p->nowrap;
- p->nowrap = 1;
-
- /* render top line */
- if (border) {
- for (c = 0; c < size; c++)
- add_char (p, br, '-');
- break_line (br, p);
- }
-
- /* render data lines */
- for (c = 0; c < tbl->numrows; c++) {
- int sizes[MAX_TABLE_COLS];
- int thetypes[MAX_TABLE_COLS];
- int centering;
- int strsize;
- int numsizes = 0;
- int width;
- add_char (p, br, (border) ? '|' : ' ');
- row = &tbl->rows[c];
- column = 0;
- for (theindex = 0; theindex < row->cols_in_row; theindex += offset) {
- width = 0;
- for (userows = 0; userows < row->cols[theindex].colspan; userows++) {
- if (width)
- width += 3;
- width += tbl->colsize[theindex + userows];
- }
- sizes[numsizes] = width;
- if (row->cols[theindex].value && width < (int) strlen (row->cols[theindex].value) && row->cols[theindex].rowspan != 1) {
- /* we can split the data, and put some on the next line */
- /* this next line makes assumptions which will break */
- tbl->rows[c + 1].cols[theindex].value = strdup (&row->cols[theindex].value[width - 1]);
- row->cols[theindex].value[width - 1] = 0;
- }
- column++;
- offset = row->cols[theindex].colspan;
- if (row->cols[theindex].url != NULLCHAR)
- start_link (p, br, row->cols[theindex].url, NULLFLINK, 0);
- add_char (p, br, NBSP);
-
- /* alignment changes, if not left */
- strsize = (row->cols[theindex].value) ? (int) strlen (row->cols[theindex].value) : 0;
- centering = width - strsize;
- if (centering < 0)
- centering = 0;
- switch (row->cols[theindex].align) {
- case TABLE_ALIGN_RIGHT:
- while (centering--)
- add_char (p, br, NBSP);
- if (row->cols[theindex].value)
- add_string (p, br, row->cols[theindex].value);
- break;
- case TABLE_ALIGN_CENTER:
- tmp = centering / 2;
- centering -= tmp;
- while (tmp--)
- add_char (p, br, NBSP);
- if (row->cols[theindex].value)
- add_string (p, br, row->cols[theindex].value);
- while (centering--)
- add_char (p, br, NBSP);
- break;
- case TABLE_ALIGN_LEFT:
- default:
- if (row->cols[theindex].value)
- add_string (p, br, row->cols[theindex].value);
- while (centering--)
- add_char (p, br, NBSP);
- break;
- }
- thetypes[numsizes] = (row->cols[theindex].rowspan == 1) ? 1 : 0;
- add_char (p, br, NBSP);
- if (row->cols[theindex].url != NULLCHAR)
- end_link (p, br, 0);
- add_char (p, br, (border) ? '|' : ' ');
- numsizes++;
- }
- break_line (br, p);
-
- /* render dividing line line */
- if (border && c < (tbl->numrows - 1)) {
- add_char (p, br, '|');
- for (theindex = 0; theindex < numsizes; theindex++) {
- int i, ch;
- ch = (thetypes[theindex]) ? '-' : NBSP; /*lint !e771 */
- add_char (p, br, ch);
- for (i = 0; i < sizes[theindex]; i++) /*lint !e771 */
- add_char (p, br, ch);
- add_char (p, br, ch);
- add_char (p, br, '|');
- }
- break_line (br, p);
- }
- }
-
- /* render bottom line */
- if (border) {
- for (c = 0; c < size; c++)
- add_char (p, br, '-');
- break_line (br, p);
- }
-
- /* and we add the caption line, if defined */
- if (tbl->caption) {
- if (!border && br->lines_in_url && *br->display_lines[br->lines_in_url - 1])
- br->display_lines[br->lines_in_url++] = strdup ("");
-
- for (c = (size - (int)(strlen (tbl->caption))) / 2; c > 0; c--)
- add_char (p, br, NBSP);
- add_string (p, br, tbl->caption);
- break_line (br, p);
- }
- p->nowrap = nowrap;
-
- if (foundimbedded) {
- break_line (br, p);
- if (br->lines_in_url && *br->display_lines[br->lines_in_url - 1])
- br->display_lines[br->lines_in_url++] = strdup ("");
- add_string (p, br, "[ End of table with one or more imbedded tables ]");
- break_line (br, p);
- }
-
- /* finally, we delete the table structure */
- free (tbl->caption);
- for (c = 0, row = tbl->rows; c < tbl->numrows; c++, row++) {
- int l;
- for (l = 0, col = row->cols; l < row->cols_in_row; l++, col++)
- free (col->value);
- }
- }
-
-
- static void
- trim_trailing_white (char *str)
- {
- int len;
-
- for (len = (int) strlen (str); len > 0; len--)
- if (str[len] == ' ')
- str[len] = 0;
- }
-
-
-
- #ifndef TEST
-
- static void
- add_cookie (char *host, char *path, time_t expires, char *name, char *value)
- {
- FILE *fp;
-
- fp = fopen (Cookiejar, APPEND_TEXT);
- if (fp != NULLFILE) {
- trim_trailing_white (host);
- trim_trailing_white (path);
- trim_trailing_white (name);
- trim_trailing_white (value);
- fprintf (fp, "%s %s %ld %s %s\n", host, path, expires, name, value);
- (void) fclose (fp);
- }
- }
-
-
-
- static void
- share_cookies (int s, char const *host, char const *component)
- {
- FILE *fp;
- char buf[512], *cp, *tmp;
- time_t thetime;
- time_t expires;
-
- (void) time (&thetime);
- fp = fopen (Cookiejar, READ_TEXT);
- if (fp != NULLFILE) {
- while (fgets (buf, 512, fp) != NULLCHAR) {
- if ((cp = strchr (buf, ' ')) == NULLCHAR)
- continue;
- *cp++ = 0;
-
- /* if not for this host, skip it */
- if (strcasecmp (host, buf))
- continue;
-
- if ((tmp = strchr (cp, ' ')) == NULLCHAR)
- continue;
- *tmp++ = 0;
-
- /* if not for this path prefix, skip it */
- if (strncmp (cp, component, strlen (cp)))
- continue;
-
- /* if already expired, skip it */
- expires = (time_t) atol (tmp);
- if (thetime > expires)
- continue;
-
- if ((cp = strchr (tmp, ' ')) == NULLCHAR)
- continue;
- if ((tmp = strchr (++cp, ' ')) == NULLCHAR)
- continue;
- *tmp++ = 0;
- rip (tmp);
-
- /* cp now points to the cookie name, and tmp to it's value */
- /* need to add code to consolidate multiple cookies to 1 line */
- usprintf (s, "Cookie: %s=%s\n", cp, tmp);
- }
- (void) fclose (fp);
- }
- }
-
-
-
- static void
- blank_status (struct browser *br)
- {
- int k, i;
-
- goto_stat (br, 0);
- for (k = 0; k < STATUS_LINES; k++)
- for (i = 0; i < SCREENwidth; i++)
- if (i != (SCREENwidth - 1) || k != (STATUS_LINES - 1))
- cputs (" ");
- }
-
-
-
- static void
- goto_stat (struct browser *br, int plusoffset)
- {
- gotoxy (1, br->current_screen_lines + plusoffset + Current->screen->statline + 1);
- }
-
-
-
- static void
- render_screen (struct browser *br)
- {
- int countdown, k, l;
- struct url_links *curlink;
- int startcol, endcol;
- char linebuf[256];
- char partial[256];
-
- clrscr ();
- curlink = &br->links[br->current_link];
- br->current_screen_lines = countdown = SCREENlength - ((Current->screen->statline * 2) + 3);
-
- if (Current->screen->statline)
- cputs (Eol);
-
- /* first put the title up at the top right */
- if (br->title) {
- countdown -= 2;
- endcol = (int) strlen (br->title);
- startcol = (SCREENwidth - 1) - endcol;
- if (startcol < 0) {
- endcol = (SCREENwidth - 1);
- startcol = 0;
- }
- while (startcol--)
- cputs (" ");
- strncpy (partial, br->title, (SCREENwidth - 1));
- cputs (partial);
- cputs (Eol);
- cputs (Eol);
- }
-
- for (k = br->current_top_line; countdown && k < br->lines_in_url; k++, countdown--) {
- if ((int) strlen (br->display_lines[k]) < br->columnoffset) {
- linebuf[0] = 0;
- if (br->columnoffset)
- strcpy (linebuf, "<");
- } else {
- strncpy (linebuf, &br->display_lines[k][br->columnoffset], (SCREENwidth + 1));
- if ((int) strlen (linebuf) > SCREENwidth) {
- linebuf[(SCREENwidth - 1)] = '>';
- linebuf[SCREENwidth] = 0;
- }
- if (br->columnoffset)
- linebuf[0] = '<';
- }
- if (br->links_per_line[k] == 0 || curlink->startline > k || curlink->endline < k) {
- /* optimize - no special treatment */
- cputs (linebuf);
- if ((int) strlen(linebuf) < SCREENwidth)
- cputs (Eol);
- continue;
- }
-
- /* we only do this if the current link is a part of this line */
- if (curlink->startline == k)
- startcol = curlink->startcolumn;
- else { /* otherwise, we are continuing on a new line */
- for (l = 0; l < SCREENwidth; l++)
- if (linebuf[l] != ' ')
- break;
- startcol = l;
- }
- if (curlink->endline == k)
- endcol = curlink->endcolumn;
- else /* otherwise, we continue on the next line */
- endcol = (int) (strlen (linebuf) - 1);
-
- if (startcol > (int) (strlen(linebuf) - 1)) {
- /* starts at end of line - optimize */
- cputs (linebuf);
- cputs (Eol);
- continue;
- }
-
- if (startcol) {
- strncpy (partial, linebuf, (unsigned int) startcol);
- partial[startcol] = 0;
- cputs (partial);
- }
- highvideo ();
- strncpy (partial, &linebuf[startcol], (unsigned int) ((endcol - startcol) + 1));
- partial[(endcol - startcol) + 1] = 0;
- cputs (partial);
- normvideo ();
- if (endcol != (int) (strlen (linebuf) - 1))
- cputs (&linebuf[endcol + 1]);
-
- cputs (Eol);
- }
- /* display a status line, and place the user on an input line */
- goto_stat (br, 0);
- if (br->has_an_index) {
- cputs (" ** Contains a searchable index - press 's' to enter search string **");
- cputs (Eol);
- } else
- cputs (Eol);
- sprintf (partial, "[Press '?' for help - Url: %-52.52s]", br->current_url);
- cputs (partial);
- if (curlink->url) {
- cputs (" link->");
- cputs (curlink->url);
- } else if (curlink->flink) {
- cputs (" form component: ");
- switch (curlink->flink->type) {
- case INPUT_PASSWORD:
- cputs ("non-echoed ");
- /* and fall through */
- case INPUT_TEXT:
- cputs ("text field - press <CR> to edit");
- break;
- case INPUT_RESET:
- cputs ("press <CR> to clear the form");
- break;
- case INPUT_SUBMIT:
- case INPUT_IMAGE:
- cputs ("press <CR> to send form");
- break;
- case INPUT_CHECKBOX:
- cputs ("press <CR> to toggle the state of this checkbox");
- break;
- case INPUT_RADIO:
- if (!curlink->flink->bool)
- cputs ("press <CR> to select this radio button");
- else
- cputs ("selected radio button");
- break;
- default:
- break;
- }
- }
- kwait (NULL);
- }
-
-
-
- static void
- spawn_telnet (int port, void *host, void *p OPTIONAL)
- {
- char *args[3];
- char *hst, portstr[10];
-
- if (port == 80)
- port = 23;
- Curproc->input = Command->input;
- args[0] = strdup ("telnet");
- args[1] = hst = strdup (host);
- sprintf (portstr, "%-d", port);
- args[2] = portstr;
-
- if (Current != Command) {
- clrscr ();
- rflush ();
- kwait (NULL);
- }
- (void) dotelnet (3, args, NULL);
-
- free (args[0]);
- free (hst);
- }
-
-
-
- static void
- spawn_ftp (int unused OPTIONAL, void *host, void *file)
- {
- char *args[4];
- char *hst, *fname, *tempname, *cp;
- FILE *fp;
-
- hst = strdup (host);
- fname = strdup (file);
-
- /* create a temp file for using ftp non-interactively */
- tempname = strdup (tmpnam (NULLCHAR));
- if ((fp = fopen (tempname, "w")) != NULLFILE) {
- if ((cp = strrchr (file, '/')) != NULLCHAR)
- *cp++ = 0;
- fprintf (fp, "anonymous\nwwwuser@%s\nbinary\ncd %s\nget %s\nbye\n", Hostname, (char *) file, cp);
- (void) fclose (fp);
-
- Curproc->input = Command->input;
- args[0] = strdup ("ftp");
- args[1] = hst;
- args[2] = tempname;
- args[3] = strdup ("prompt");
-
- if (Current != Command) {
- clrscr ();
- rflush ();
- kwait (NULL);
- }
- (void) doftp (4, args, NULL);
- unlink (tempname);
-
- free (args[0]);
- free (args[3]);
- }
-
- free (hst);
- free (fname);
- free (tempname);
- }
-
-
-
- static void
- send_blank_lines (int count)
- {
- while (count--)
- cputs (Eol);
- }
-
-
-
- static void
- send_mailto (char *addr)
- {
- char *args[5];
- char *tempname;
- FILE *fp;
- char buf[128];
- char subject[128];
-
- /* create a temp file for the email message */
- sprintf (buf, "<%s", tmpnam (NULLCHAR));
- tempname = strdup (buf);
-
- if ((fp = fopen (&tempname[1], "w")) != NULLFILE) {
- clrscr ();
- send_blank_lines (3);
- cputs ("Enter the subject for the email message:");
- send_blank_lines (2);
- Current->ttystate.edit = Current->ttystate.echo = 1;
-
- kwait (NULL);
- (void) recvline (Curproc->input, (unsigned char *) subject, 128);
-
- send_blank_lines (2);
- cputs ("Enter the body of the message: ('/ex' to end)");
- cputs (Eol);
-
- for ( ; ; ) {
- (void) recvline (Curproc->input, (unsigned char *) buf, 128);
- if (!strncasecmp (buf, "/ex", 3))
- break;
- fputs (buf, fp);
- kwait (NULL);
- }
- (void) fclose (fp);
-
- args[0] = strdup ("sendmail");
- args[1] = addr;
- sprintf (buf, "wwwuser@%s", Hostname);
- args[2] = buf;
- args[3] = subject;
- args[4] = tempname;
-
- (void) dosendmail (5, args, NULL);
- unlink (tempname);
-
- clrscr ();
- send_blank_lines (3);
- cputs ("The email message has been sent!");
- cputs (Eol);
- cputs ("Press any key to return to the current page...");
- kwait (NULL);
- Current->ttystate.edit = Current->ttystate.echo = 0;
- (void) rrecvchar (Curproc->input);
- free (args[0]);
- }
-
- free (tempname);
- }
-
-
-
-
- static char *
- encode_post (char *str)
- {
- char *retval, *cp;
- static char hexchar[] = "0123456789ABCDEF";
-
- if (str == NULLCHAR || !*str)
- return (strdup (""));
-
- cp = retval = (char *) callocw (1, strlen (str) * 2);
- while (*str) {
- if (*str == ' ') {
- *cp++ = '+';
- str++;
- } else if (!strchr ("$-_.!*+'(),;:@&=?/%", *str))
- *cp++ = *str++;
- else {
- *cp++ = '%';
- *cp++ = hexchar[*str / 16];
- *cp++ = hexchar[*str++ % 16];
- }
- }
- return retval;
- }
-
-
-
- static int
- gethead (const char *url, char *location, char *modified, char *content)
- {
- FILE *fp;
- char type[12], host[100], component[512];
- int port, s, c;
- char *tmp, *cp;
- struct sockaddr_in fsocket;
-
- if (url == NULLCHAR || (location == NULLCHAR && modified == NULLCHAR && content == NULLCHAR))
- return 0;
-
- if (location != NULLCHAR)
- *location = 0;
-
- if (modified != NULLCHAR)
- *modified = 0;
-
- if (content != NULLCHAR)
- *content = 0;
-
- fp = tmpfile ();
- if (fp == NULLFILE)
- return -1; /* shouldn't happen */
-
- tmp = strdup (url);
- if (disect_url (tmp, type, host, &port, component)) {
- (void) fclose (fp);
- return 0;
- }
- if (!*host) {
- strncpy (host, component, 100);
- strcpy (component, "/");
- }
- free (tmp);
-
- if (strcasecmp (type, "http")) {
- /* don't do anything, for now */
- (void) fclose (fp);
- return 0;
- }
-
- s = http_connect (host, port, &fsocket);
- if (s == -1) {
- (void) fclose (fp);
- return -1;
- }
-
- if ((cp = strchr (component, '#')) != NULLCHAR)
- *cp = 0;
-
- /* send the request to the server */
- usprintf (s, "HEAD %s HTTP/1.0\nHost: %s\nUser-Agent: %s\n",
- component, Hostname, shortversion);
- usputs (s, "Accept-Language: en\nPragma: no-cache\n");
- usprintf (s, "Cache-Control: no-cache\nFrom: wwwuser@%s\n\n", Hostname);
-
- /* then while connection still open, store data into 'fp' */
- while ((c = recvchar (s)) != EOF)
- fputc (c, fp);
-
- close_s (s);
- rewind (fp);
-
- while (fgets (component, 128, fp)) {
- rip (component);
- if (!*component)
- break;
- if (content != NULLCHAR && !strncasecmp (component, "Content-type: ", 14))
- strcpy (content, &component[14]);
-
- if (location != NULLCHAR && !strncasecmp (component, "Location: ", 10))
- strcpy (location, &component[10]);
-
- if (modified != NULLCHAR && !strncasecmp (component, "Last-Modified: ", 15))
- strcpy (modified, &component[15]);
-
- /* else, bitbucket any other headers, for now */
- }
- (void) fclose (fp);
- return 1;
- }
-
-
-
- int
- dobrowseremail (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
- {
- char buf[256];
-
- if (argc < 2)
- tprintf ("%s\n", BrowserEmail);
- else {
- free (BrowserEmail);
- strcpy (buf, argv[1]);
- if (!strchr (buf, '@')) {
- strcat (buf, "@");
- strcat (buf, Hostname);
- }
- BrowserEmail = strdup (buf);
- }
- return 0;
- }
-
-
-
- int
- dobrowsercheck (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
- {
- int timeout;
- int retval;
- char modified[128], buf[256], *cp, *tname;
- int doit, found;
- FILE *fp, *fpout;
- char *bptr;
- char *bareurl, *origurl;
-
- if (argc != 3) {
- tputs ("Usage: browsercheck <numseconds> <complete url>\n");
- return 1;
- }
-
- origurl = strdup (argv[2]);
- bareurl = strdup (origurl);
- cp = strchr (bareurl, '?');
- if (cp)
- *cp = 0;
- timeout = atoi (argv[1]);
- if (timeout) {
- kalarm (timeout * 1000);
- retval = gethead (bareurl, NULLCHAR, modified, NULLCHAR);
- kalarm (0);
- if (retval == -1)
- tprintf ("Couldn't obtain url: %s\n", bareurl);
- else {
- /* check for last update time */
- doit = 0;
- fp = fopen (CheckedURLs, READ_TEXT);
- if (fp != NULLFILE) {
- while (fgets (buf, 256, fp)) {
- rip (buf);
- cp = strchr (buf, ' ');
- if (cp == NULLCHAR)
- continue;
- *cp++ = 0;
- if (!strcasecmp (bareurl, buf)) {
- if (!strcasecmp (cp, modified))
- doit = 1;
- }
- }
- (void) fclose (fp);
- }
- /* if doit != 0, it is new or newer */
- if (doit) {
- tprintf ("\nURL '%s' has NOT been updated!\n", bareurl);
- return 0;
- }
-
- /* if newer, prompt (y/n/later) */
- if (!*modified)
- tprintf ("\nURL '%s' has no\nmodification time/date stamp\nCannot tell if it has been updated.\nDisplay it? (Yes, No) [y/n] ", bareurl);
- else
- tprintf ("\nURL '%s' has been updated.\nDisplay it? (Yes, No, or Later) [y/n/l] ", bareurl);
- tflush ();
- (void) recvline (Curproc->input, (unsigned char *) buf, 256);
- doit = tolower (*buf);
-
- if (doit == 'y' || doit == 'n') {
- /* update last update time */
- tname = strdup (CheckedURLs);
- tname[strlen(tname) - 1] = '_';
-
- fp = fopen (CheckedURLs, READ_TEXT);
- fpout = fopen (tname, WRITE_TEXT);
- if (fpout != NULLFILE) {
- found = 0;
- if (fp != NULLFILE) {
- while (fgets (buf, 256, fp)) {
- cp = strchr (buf, ' ');
- if (cp == NULLCHAR)
- continue;
- *cp = 0;
- if (!strcasecmp (bareurl, buf)) {
- strcpy (&cp[1], modified);
- strcat (&cp[1], "\n");
- found = 1;
- }
- *cp = ' ';
- fputs (buf, fpout);
- }
- (void) fclose (fp);
- }
- if (!found)
- fprintf (fpout, "%s %s\n", bareurl, modified);
- (void) fclose (fpout);
- }
- (void) unlink (CheckedURLs);
- (void) rename (tname, CheckedURLs);
- free (tname);
-
- if (doit == 'y') {
- sprintf (buf, "browser %s", origurl);
- bptr = _variable_expansion (strdup (buf));
- (void) cmdparse (Cmds, bptr, NULL);
- free (bptr);
- }
- }
- }
- }
- free (bareurl);
- free (origurl);
- return 0;
- }
-
-
-
- char *
- obtain_statline_marquee (void)
- {
- struct browser *br;
- char buf[200], *cp;
- FILE *fp;
-
- br = (struct browser *) callocw (1, sizeof (struct browser));
- fp = tmpfile ();
- if (fp == NULLFILE || br == NULLBROWSER)
- return NULLCHAR; /* shouldn't happen */
-
- log (-1, "Updating Statusline News Service from %s", HEADLINENewsHost);
- kalarm (120 * 1000);
- sprintf (buf, "http://%s/headline_news_retrieval_service", Hostname);
- if (http_url_to_file (br, buf, HEADLINENewsHost, 80, HEADLINENewsUrl, NULLCHAR, fp, NULLCHAR, 0, NULLCHAR, 1) == 0)
- parse_url (br, fp, 1);
- kalarm (0);
-
- (void) fclose (fp);
- cp = br->marquee;
- br->marquee = NULLCHAR;
- clear_browser (br);
- return (cp);
- }
-
-
-
- /* screen position is ALREADY set to the line desired */
- static void
- scroll_marquee (struct browser *br)
- {
- if (br->marquee == NULLCHAR)
- return;
-
- goto_stat (br, 0);
- marquee_display (br->marquee, &br->marquee_position);
- }
-
-
-
- int
- dobrowser (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
- {
- struct session *sp = NULLSESSION;
- struct browser *br;
- struct formlink *fl, *fl2;
- int c, k;
- int renderit = 1;
- int done = 0;
- int skipsession = 0;
- char buf[128], newurl[256];
- char *cp, *cp2;
- int len;
- struct url_links *lk;
- int godown;
-
- /* Make sure this comes from console */
- if (Curproc->input != Command->input)
- return 0;
-
- if (!strncasecmp (argv[1], "telnet://", 9) ||
- !strncasecmp (argv[1], "ftp://", 6))
- skipsession = 1;
-
- /* Allocate a session descriptor */
- if (!skipsession) {
- if ((sp = newsession ("browser", TELNET, 0)) == NULLSESSION) {
- tputs (TooManySessions);
- return 1;
- }
- }
-
- br = (struct browser *) callocw (1, sizeof (struct browser));
- br->current_screen_lines = SCREENlength - ((Current->screen->statline * 2) + 3);
- if (strstr (argv[1], "//"))
- strcpy (newurl, argv[1]);
- else
- sprintf (newurl, "http://%s", argv[1]);
- c = get_url (br, newurl, NULLCHAR, 0, NULLCHAR, 1);
- if (c == 1) {
- if (!skipsession)
- freesession (sp);
- goto cleanup;
- }
- /* this SHOULDN'T ever happen... */
- if (sp == NULLSESSION)
- return 1;
-
- sp->ttystate.edit = sp->ttystate.echo = 0;
-
- /* real routine will call render_screen, then loop on input */
- while (!done) {
- if (renderit) {
- render_screen (br);
- renderit = 0;
- }
- kalarm (100);
- c = rrecvchar (Curproc->input);
- kalarm (0);
- if (c == -1) {
- scroll_marquee (br);
- continue;
- }
- c = tolower (c);
-
- switch (c) {
- case 'n': /* move to next line of file */
- if (br->current_top_line < (br->lines_in_url - 1)) {
- br->current_top_line++;
- renderit = 1;
- }
- break;
- case 'p': /* move to previous line of file */
- if (br->current_top_line) {
- br->current_top_line--;
- renderit = 1;
- }
- break;
- case '\t':
- case 'd': /* move forward one link in the file */
- move_down: if (br->current_link < (br->link_count - 1)) {
- br->current_link++;
- renderit = 1;
- goto adj_check;
- }
- break;
- case 'u': /* move back one link in the file */
- if (br->current_link) {
- br->current_link--;
- renderit = 1;
- adj_check: /* also, adjust the screen window, if needed */
- if (br->links[br->current_link].startline < br->current_top_line ||
- br->links[br->current_link].endline >= br->current_top_line + br->current_screen_lines)
- br->current_top_line = br->links[br->current_link].startline;
- } else if (br->current_top_line) {
- br->current_top_line = 0;
- renderit = 1;
- }
- break;
- case 'h': /* display history linkbacks */
- clrscr ();
- send_blank_lines (3);
- cputs ("\t\tLinkback History List");
- send_blank_lines (2);
- for (k = 0; k < br->total_in_linkback; k++) {
- cputs ("\t");
- cputs ((k == br->current_linkback) ? "*" : " ");
- cputs (br->linkback[k]);
- cputs (Eol);
- }
- send_blank_lines (3);
- cputs ("\t\tPress any key to return to the active page");
-
- (void) rrecvchar (Curproc->input);
- renderit = 1;
- break;
- case '<': /* shift screen left - only if already shifted right */
- if (br->columnoffset) {
- br->columnoffset -= (SCREENwidth / 2);
- if (br->columnoffset < 0)
- br->columnoffset = 0;
- renderit = 1;
- }
- break;
- case '>': /* shift screen right - only if anymore to right */
- if (br->columnoffset + (SCREENwidth / 2) < br->longestline - (SCREENwidth / 2)) {
- br->columnoffset += (SCREENwidth / 2);
- renderit = 1;
- }
- break;
- case '?': /* do a help display for the user */
- /* need to complete this */
- clrscr ();
-
- send_blank_lines (3);
- cputs ("\t\t'n'\tMoves the screen to the next line");
- cputs (Eol);
- cputs ("\t\t'p'\tMoves the screen to the previous line");
- cputs (Eol);
- cputs ("\t\t' '\tMoves the screen down one page");
- cputs (Eol);
- cputs ("\t\t'-'\tMoves the screen up one page");
- cputs (Eol);
- cputs ("\t\t'>'\tShifts screen right one half page (if needed)");
- cputs (Eol);
- cputs ("\t\t'<'\tShifts screen left one half page (if needed)");
- send_blank_lines (2);
-
- cputs ("\t\t'd'\tActivates the next link down on page (<TAB> also)");
- cputs (Eol);
- cputs ("\t\t'u'\tActivates the next link up on page");
- send_blank_lines (2);
-
- cputs ("\t\t'g'\tGo to a new URL");
- cputs (Eol);
- cputs ("\t\t'r'\tReloads the current URL");
- cputs (Eol);
- cputs ("\t\t'h'\tDisplays the linkback list history");
- cputs (Eol);
- cputs ("\t\t'f'\tSelects the link one forward from here");
- cputs (Eol);
- cputs ("\t\t'b'\tSelects the link one backward from here");
- send_blank_lines (2);
-
- cputs ("\t\t's'\tSearches an index (if present on the page)");
- send_blank_lines (2);
-
- cputs ("\t\t'q'\tQuits the browser session");
- cputs (Eol);
- cputs ("\t\t'?'\tDisplays this help summary");
- send_blank_lines (2);
-
- cputs ("\t\t\t<CR> selects the active link or form component");
- send_blank_lines (3);
-
- cputs ("\t\tPress any key to return to the active page");
-
- (void) rrecvchar (Curproc->input);
- renderit = 1;
- break;
- case 'q': /* quit the browser */
- done = 1;
- break;
- case 's': /* search the index - if present */
- if (br->has_an_index) {
- blank_status (br);
- Current->ttystate.edit = Current->ttystate.echo = 1;
- goto_stat (br, 1);
- cputs ("Enter Search String: ");
-
- kwait (NULL);
- (void) recvline (Curproc->input, (unsigned char *) buf, 128);
- rip (buf);
-
- Current->ttystate.edit = Current->ttystate.echo = 0;
- sprintf (newurl, "%s?%s", br->current_url, buf);
- (void) get_url (br, newurl, NULLCHAR, 0, NULLCHAR, 1);
- renderit = 1;
- }
- break;
- case 'g': /* go to an new url */
- blank_status (br);
- Current->ttystate.edit = Current->ttystate.echo = 1;
- goto_stat (br, 0);
- cputs ("Enter in a new URL in which to visit (if another site, start with '//')");
- cputs (Eol);
- cputs (" Enter the complete URL: ");
-
- kwait (NULL);
- (void) recvline (Curproc->input, (unsigned char *) buf, 128);
- rip (buf);
-
- Current->ttystate.edit = Current->ttystate.echo = 0;
- cp = rebuild_url (br, strdup (buf));
- if (cp != NULLCHAR)
- (void) get_url (br, cp, NULLCHAR, 0, NULLCHAR, 1);
- free (cp);
- renderit = 1;
- break;
- case ' ': /* down a page */
- br->current_top_line += (SCREENLENGTH - (Current->screen->statline + 4));
- if (br->current_top_line >= br->lines_in_url)
- br->current_top_line = br->lines_in_url - 3;
- renderit = 1;
- break;
- case '-': /* up a page */
- br->current_top_line -= (SCREENLENGTH - (Current->screen->statline + 4));
- if (br->current_top_line < 0)
- br->current_top_line = 0;
- renderit = 1;
- break;
- case '\r':
- case '\n': /* traverse the current link */
- if (br->link_count == 0)
- break; /* no link to traverse */
- lk = &br->links[br->current_link];
- if (lk->url) {
- godown = 0;
- (void) get_url (br, lk->url, NULLCHAR, 0, NULLCHAR, 1);
- } else {
- if (lk->flink == NULLFLINK)
- break;
-
- /* must be a form component */
- godown = 1;
- switch (lk->flink->type) {
- case INPUT_CHECKBOX:
- lk->flink->bool ^= 1;
- br->display_lines[lk->flink->line][lk->flink->col] = (lk->flink->bool) ? 'X' : '_';
- break;
- case INPUT_RADIO:
- if (lk->flink->bool)
- break;
- /* we need to insure that only this one radio button in this group is selected */
-
- for (fl = br->form->flink; fl != NULLFLINK; fl = fl->next) {
- if (fl->type == INPUT_RADIO && !strcmp (fl->name, lk->flink->name)) {
- br->display_lines[fl->line][fl->col] = '_';
- fl->bool = 0;
- }
- }
- br->display_lines[lk->flink->line][lk->flink->col] = '*';
- lk->flink->bool = 1;
- break;
- case INPUT_TEXT:
- case INPUT_PASSWORD:
- blank_status (br);
- if (lk->flink->type == INPUT_TEXT)
- Current->ttystate.echo = 1;
- Current->ttystate.edit = 1;
- goto_stat (br, 1);
- cputs ("Enter Text String: ");
-
- kwait (NULL);
- k = recvline (Curproc->input, (unsigned char *) buf, (unsigned int) (lk->flink->size + 1));
- rip (buf);
-
- Current->ttystate.edit = Current->ttystate.echo = 0;
- if (!*buf)
- break;
- cp = &br->display_lines[lk->flink->line][lk->flink->col];
- for (len = 0; len < lk->flink->size; len++)
- cp[len] = '_';
- if (lk->flink->type == INPUT_TEXT)
- strncpy (cp, buf, strlen(buf));
- free (lk->flink->data);
- lk->flink->data = strdup (buf);
-
- /* if the user gave a string too long, then eat the rest of the line */
- if (k == lk->flink->size)
- while ((c = rrecvchar (Curproc->input)) != '\n')
- ;
-
- break;
- case INPUT_RESET:
- for (fl = br->form->flink; fl != NULLFLINK; fl = fl->next) {
- switch (fl->type) {
- case INPUT_CHECKBOX:
- br->display_lines[fl->line][fl->col] = '_';
- fl->bool = 0;
- break;
- case INPUT_TEXT:
- case INPUT_PASSWORD:
- free (fl->data);
- fl->data = NULLCHAR;
- cp = &br->display_lines[fl->line][fl->col];
- for (len = 0; len < fl->size; len++)
- cp[len] = '_';
- break;
- default:
- break;
- }
- }
- godown = 0;
- break;
- case INPUT_SUBMIT:
- case INPUT_IMAGE:
- /* formulate data to send in HTTP request */
- newurl[0] = 0;
-
- /* we start with the checkboxes, and handle them separately, since
- you can have several with the same name, and the values are to be
- concatenated together in one variable. */
- for (fl = br->form->flink; fl != NULLFLINK; fl = fl->next)
- if (fl->type == INPUT_CHECKBOX)
- fl->size = 0; /* used to prevent repeats */
-
- for (fl = br->form->flink; fl != NULLFLINK; fl = fl->next) {
- if (fl->type != INPUT_CHECKBOX || fl->size == 255)
- continue;
- cp = encode_post (fl->value);
- sprintf (buf, "%s%s=%s", (newurl[0]) ? "&" : "", fl->name, cp);
- free (cp);
- strcat (newurl, buf);
- fl->size = 255;
- for (fl2 = fl->next; fl2 != NULLFLINK; fl2 = fl2->next) {
- if (fl2->type != INPUT_CHECKBOX || fl2->size == 255 || strcmp (fl->name, fl2->name))
- continue;
- cp = encode_post (fl2->value);
- strcat (newurl, ",");
- strcat (newurl, cp);
- free (cp);
- fl2->size = 255;
- }
- }
-
- /* now we handle everything else BUT the checkboxes. */
- for (fl = br->form->flink; fl != NULLFLINK; fl = fl->next) {
- switch (fl->type) {
- case INPUT_SUBMIT:
- if (fl->name == NULLCHAR)
- continue;
- /* else, fall through */
- case INPUT_TEXT:
- case INPUT_PASSWORD:
- cp = encode_post (fl->data);
- sprintf (buf, "%s%s=%s", (newurl[0]) ? "&" : "", fl->name, cp);
- free (cp);
- break;
- case INPUT_HIDDEN:
- add_to_request: cp = encode_post (fl->value);
- sprintf (buf, "%s%s=%s", (newurl[0]) ? "&" : "", fl->name, cp);
- free (cp);
- break;
- case INPUT_RADIO:
- if (!fl->bool)
- continue;
- goto add_to_request;
- default:
- continue;
- }
- strcat (newurl, buf);
- }
- /* send the post here */
- cp = br->form->action;
- br->form->action = NULLCHAR;
- cp2 = br->form->enctype;
- br->form->enctype = NULLCHAR;
- #if 0
- tcmdprintf ("Would post here: '%s'\n", cp);
- #else
- (void) get_url (br, cp, newurl, br->form->method, cp2, 1);
- #endif
- free (cp);
- free (cp2);
- godown = 0;
- break;
- default:
- godown = 0;
- break;
- }
- }
- renderit = 1;
- if (godown)
- goto move_down;
- break;
- case 'f': /* go forward one link */
- if (br->current_linkback < (br->total_in_linkback - 1)) {
- br->current_linkback++;
- goto reload_link;
- }
- break;
- case 'b': /* go back one link */
- if (br->current_linkback) {
- br->current_linkback--;
- reload_link: (void) get_url (br, br->linkback[br->current_linkback], NULLCHAR, 0, NULLCHAR, 0);
- renderit = 1;
- }
- break;
- case 'r': goto reload_link;
- case 0:
- case 1:
- renderit = 1;
- break;
- default: break;
- }
-
- }
-
- close_s (sp->s);
- sp->s = -1;
-
- blank_status (br);
- goto_stat (br, 1);
- cputs (" ");
- (void) keywait (NULLCHAR, 1);
- freesession (sp);
-
- for (c = 0; c < br->total_in_linkback; c++)
- free (br->linkback[c]);
- cleanup:
- while (br->myrealms) {
- free (br->myrealms->host);
- free (br->myrealms->realm);
- free (br->myrealms->auth);
- br->myrealms = br->myrealms->next;
- }
- clear_browser (br);
- free (br);
- return 0;
- }
-
-
-
- #else
- struct browser brow;
-
-
-
- void
- kwait (void *ignore)
- {
- }
-
-
- char *
- strlwr(s)
- char *s;
- {
- register char *p = s;
-
- while (*p)
- *p = (char) tolower (*p), p++;
- return s;
- }
-
-
-
- void
- rip(s)
- register char *s;
- {
- register char *cp;
-
- if((cp = strchr(s,'\n')) != NULLCHAR)
- *cp = '\0';
- }
-
-
-
- void
- main (int argc, char *argv[])
- {
- FILE *fp;
- int k;
- struct formlink *fl;
-
- setbuf (stdout, NULL);
- brow.host = strdup ("www.lantz.com");
- brow.current_url = strdup ("/index.html");
- fp = fopen ("/tmp/index.html", "r");
- parse_url (&brow, fp, 0);
- (void) fclose (fp);
-
- printf ("Current URL: %s\nHost: %s\nPort: %d\nUrlLines: %d\n", brow.current_url,
- brow.host, brow.port, brow.lines_in_url);
- printf ("TopLine: %d\nTitle: %s\n\n", brow.current_top_line, brow.title);
-
- for (k = 0; k < brow.lines_in_url; k++)
- printf ("Line #%02d (%d) [%d]: %s\n", k,
- strlen (brow.display_lines[k]),
- brow.links_per_line[k], brow.display_lines[k]);
-
- printf ("\nLinkCount: %d\nCurrentLink: %d\n\n", brow.link_count, brow.current_link);
- for (k = 0; k < brow.link_count; k++)
- printf ("Link #%02d: startline=%d, startcol=%d, endline=%d, endcol=%d, url=%s\n",
- k, brow.links[k].startline, brow.links[k].startcolumn,
- brow.links[k].endline, brow.links[k].endcolumn,
- brow.links[k].url);
- if (brow.form != NULLFORM) {
- printf ("\nForm active:\n\tURL: %s\n\tMethod: %d\n\tEnctype: %s\n\n",
- brow.form->action, brow.form->method, brow.form->enctype);
- for (fl = brow.form->flink; fl != NULLFLINK; fl = fl->next)
- printf ("Link:\tType: %d - line=%d, col=%d\tBool=%d - Data=%s\n"
- "\tName=%s\tValue=%s\n\tAlign=%s - Size=%d - Maxlength=%d\n\n",
- fl->type, fl->line, fl->col, fl->bool, fl->data,
- fl->name, fl->value, fl->align, fl->size, fl->maxlength);
- }
- }
-
- #endif
-
- #endif /* BROWSER */
-